﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Net.Http;
using System.Text;
using System.Threading.Tasks;
using Joy.Erp.Ufida.Core;
using Microsoft.Extensions.Caching.Distributed;
using Microsoft.Extensions.Caching.Memory;
using Microsoft.Extensions.Logging;
using Newtonsoft.Json;
using Volo.Abp;
using Volo.Abp.Caching;

namespace Joy.Erp.Ufida.Production
{
    public class MOUfidaAppService : UfidaAppService, IMOUfidaAppService
    {
        private readonly IMemoryCache _memoryCache;
        protected ITokenUfidaAppService TokenUfidaAppService =>
            LazyServiceProvider.LazyGetRequiredService<ITokenUfidaAppService>();

        public MOUfidaAppService(IMemoryCache memoryCache)
        {
            _memoryCache = memoryCache;
        }

        public async Task<MOUfidaDto> GetLineAsync(long lineid, DateTime start, DateTime end)
        {
            var u9list = await GetAllAsync(start, end);
            return u9list.FirstOrDefault(x => x.ID == lineid);
        }

        public async Task<List<MOUfidaDto>> GetLinesAsync(long id, DateTime start, DateTime end)
        {
            var u9list = await GetAllAsync(start, end);
            return u9list.Where(x => x.ID == id).ToList();
        }

        public async Task<MOUfidaDto> FindByDocNoAsync(string docNo, DateTime start, DateTime end)
        {
            var u9list = await GetAllAsync(start, end);
            return u9list.FirstOrDefault(x => x.DocNo == docNo);
        }

        public async Task<List<MOUfidaDto>> GetAllAsync(DateTime start, DateTime end)
        {
            var cacheKey = $"{typeof(MOUfidaAppService).FullName}|{start:yyyyMMdd}|{end:yyyyMMdd}";

            if (!_memoryCache.TryGetValue(cacheKey, out List<MOUfidaDto> cachedData))
            {
                cachedData = await GetAllFromApiAsync(start, end);

                var cacheOptions = new MemoryCacheEntryOptions
                {
                    AbsoluteExpirationRelativeToNow = TimeSpan.FromMinutes(30),
                    Size = cachedData.Count, // 用于缓存大小控制
                };

                _memoryCache.Set(cacheKey, cachedData, cacheOptions);
            }
            return cachedData;
        }

        private async Task<List<MOUfidaDto>> GetAllFromApiAsync(DateTime start, DateTime end)
        {
            var token = await TokenUfidaAppService.GetTokenAsync();
            var queryUrl = TokenUfidaAppService.U9ApiConfig.BaseUrl.AppendSegments(
                $"webapi/QueryCommon/QueryInfoBySql"
            );

            var httpRequest = new HttpRequestMessage(HttpMethod.Post, queryUrl);
            httpRequest.Headers.Add("token", token);

            var sqlBuilder = new StringBuilder();
            sqlBuilder.Append("select ");
            sqlBuilder.Append("  'MO' as TableName ");
            sqlBuilder.Append("  ,mo.ID ");
            sqlBuilder.Append("  ,mo.DocNo ");
            sqlBuilder.Append("  ,mo.BusinessDate ");
            sqlBuilder.Append("  ,mo.DocState ");
            sqlBuilder.Append("  ,mo.MODocType as DocumentType ");
            sqlBuilder.Append("  ,mo.ItemMaster ");
            sqlBuilder.Append("  ,mo.ProductQty ");
            sqlBuilder.Append("  ,mo.TotalCompleteQty ");
            sqlBuilder.Append("  ,mo.SeibanCode ");
            sqlBuilder.Append("  ,ev.Code as DemandCode ");
            sqlBuilder.Append("  ,mo.StartDate ");
            sqlBuilder.Append("  ,mol.ID as LineID ");
            sqlBuilder.Append("  ,mol.DocLineNo ");
            sqlBuilder.Append("  ,mol.ItemMaster as LineItemMaster ");
            sqlBuilder.Append("  ,mol.ActualReqQty as Quantity ");
            sqlBuilder.Append("  ,mol.IssuedQty as IssuedQuantity ");
            sqlBuilder.Append("  ,mo.CreatedOn ");
            sqlBuilder.Append("from MO_MO mo ");
            sqlBuilder.Append("  left join MO_MOPickList mol on mol.MO = mo.ID ");
            sqlBuilder.Append("  inner join MO_MO_Trl motrl on mo.ID = motrl.ID and motrl.SysMLFlag='zh-CN' ");
            sqlBuilder.Append("  inner join Base_Organization o on o.ID = mo.Org   ");
            sqlBuilder.Append("  left join UBF_Sys_ExtEnumValue ev on ev.EValue = mo.DemandCode and ev.ExtEnumType = (select ID from UBF_Sys_ExtEnumType where Code='UFIDA.U9.CBO.Enums.DemandCodeEnum') ");
            sqlBuilder.Append("where 1=1");
            sqlBuilder.Append($"  and mo.CreatedOn >= '{start.ToString("yyyyMMdd")}' ");
            sqlBuilder.Append($"  and mo.CreatedOn <= '{end.ToString("yyyyMMdd")}' ");
            sqlBuilder.Append($"  and o.Code = '{SourceConfig.OrgCode}' ");

            var jsonObj = new { SqlString = sqlBuilder.ToString() };
            var jsonObjStr = JsonConvert.SerializeObject(jsonObj);
            httpRequest.Content = new StringContent(jsonObjStr, Encoding.UTF8, "application/json");
            Logger.LogInformation($"开始请求Api接口，接口地址: {queryUrl}, 正文内容: {jsonObjStr}");

            var httpClient = new HttpClient();
            var response = await httpClient.SendAsync(httpRequest);
            response.HandStatusCode(queryUrl);

            var responseContent = await response.Content.ReadAsStringAsync();
            Logger.LogInformation($"开始解析Api返回结果");

            try
            {
                var resultObj = JsonConvert.DeserializeObject<CommonDto<MOUfidaDto>>(
                    responseContent
                );
                if (!resultObj.Success)
                    throw new BusinessException("BasicArchives:104").WithData(
                        "ErrorMessage",
                        resultObj.ResMsg
                    );

                Logger.LogInformation($"Api接口请求成功，返回数据{resultObj.Data.Count}条");

                return resultObj.Data;
            }
            catch (JsonException ex)
            {
                throw new BusinessException("BasicArchives:103", innerException: ex).WithData(
                    "DtoType",
                    typeof(CommonDto).Name
                );
            }
        }
    }
}
